662. 二叉树最大宽度

662. 二叉树最大宽度

Similar Question

leading to the advanced question

Solution Tips

关键就是父与子的索引关系

方案一: BFS

假设父节点的索引为 i, 那么子节点的索引为 left: 2^i, right: 2^i + 1

var widthOfBinaryTree = function(root) {
    // 父节点的 index 和子节点的 index 的关系?
    // 父节点为 i, 则左子节点为 2*i, 右子节点为 2*i + 1
    root.index = 0;
    const queue = [root];
    let maxWidth = 0;

    while (queue.length) {
        const n = queue.length;
        let firstNotNullIndex = -1;
        for (let i = 0; i < n; i++) {
            const node = queue.shift();
            if (node !== null) {
                if (firstNotNullIndex === -1) {
                    firstNotNullIndex = node.index;
                }
                else {
                    maxWidth = Math.max(maxWidth, node.index - firstNotNullIndex);
                }

                if (node.left) {
                    // index 有可能溢出, 如何安全计算呢? 虽然关心的是差值, 但是确实有可能就是溢出了
                    // 不能因为 case 是挨在一起的就针对性的处理
                    // 做法就是相对于第一个节点做差值, 这样只要单层节点不是溢出的, index 也不会溢出
                    node.left.index = 2 * node.index - firstNotNullIndex;
                    queue.push(node.left);
                }

                if (node.right) {
                    node.right.index = 2 * node.index + 1 - firstNotNullIndex;
                    queue.push(node.right);
                }
            }
        }
    }

    return maxWidth;
};

方案二: DFS

没办法一层层的比较,所以需要用哈希表记录 depth ,每次到了 depth 都去与这一层第一个遍历到的节点比较 index

超时方案: 错误思路

var widthOfBinaryTree = function(root) {
    // 层次遍历改版, 就算是 null 也得继续 push
    // 需要根据深度来判断是否要用 null 填充
    const queue = [root];
    let maxWidth = 0;

    while (queue.length) {
        const n = queue.length;
        let shouldPad = false;
        let firstNotNUll = -1;

        for (let i = 0; i < n; i++) {
            const node = queue.shift();
            if (node !== null) {
                // 只要其中一个不是 null, 下一行就需要用 null 填充
                shouldPad = true;
                queue.push(node.left);
                queue.push(node.right);
                if (firstNotNUll === -1) {
                    firstNotNUll = i;
                }
                else {
                    // 计算该层的最大宽度
                    maxWidth = Math.max(maxWidth, i - firstNotNUll);
                }
            }
            else if (shouldPad) {
                queue.push(null);
                queue.push(null);
            }
        }
    }

    // 超时了, 换思路, 贪心思想, 直接找到最左边的节点和最右边的节点? 不行, 考虑菱形的二叉树
    // 每次左就加1, 每次右也加1, 反过来就减1
    // 最右侧节点的索引: 2^n - 1 - ()
    // 最左侧节点的索引: 2^(n - d) - 1
    // 每次 left d++, 每次 right d--, 最小为 0

    return maxWidth;
};